package com.zw.cloud.mybatis.plus.task.stenter;

import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Sets;
import com.zw.cloud.common.utils.BigDecimalUtils;
import com.zw.cloud.mybatis.plus.entity.stenter.BaseShapingParamConfig;
import com.zw.cloud.mybatis.plus.entity.stenter.BaseTenterCraft;
import com.zw.cloud.mybatis.plus.entity.stenter.OptimizeCraft;
import com.zw.cloud.mybatis.plus.entity.stenter.OptimizeCraftPageDTO;
import com.zw.cloud.mybatis.plus.enums.OptimizeCraftEnum;
import com.zw.cloud.mybatis.plus.enums.StenterInfluxDBEnum;
import com.zw.cloud.mybatis.plus.service.api.stenter.IBaseShapingParamConfigService;
import com.zw.cloud.mybatis.plus.service.api.stenter.IBaseTenterCraftService;
import com.zw.cloud.mybatis.plus.service.api.stenter.IOptimizeCraftService;
import com.zw.cloud.mybatis.plus.service.api.stenter.IProductRecordDetailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 定型可优化工艺
 */
@Slf4j
@Component
public class OptimizeCraftTask {


    @Autowired
    private IOptimizeCraftService optimizeCraftService;
    @Autowired
    private IProductRecordDetailService productRecordDetailService;
    @Autowired
    private IBaseTenterCraftService baseTenterCraftService;
    @Autowired
    private IBaseShapingParamConfigService baseShapingParamConfigService;


    public void optimizablCraftTask() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime localDateTime = now.minusDays(1);
        LocalDateTime startTime = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), localDateTime.getDayOfMonth(), 0, 0, 0);
        LocalDateTime endTime = startTime.plusDays(1);
        optimizablCraftTaskCore(startTime, endTime);
    }

    public void optimizablCraftTaskCore(LocalDateTime startTime,LocalDateTime endTime) {
        log.info("[OptimizablCraftTask]startTime is {},endTime is {}",startTime,endTime);
        List<Long> baseTenterCraftIdList = productRecordDetailService.queryBaseTenterCraftId(startTime, endTime);
        if (CollectionUtils.isEmpty(baseTenterCraftIdList)) {
            log.info("[OptimizablCraftTask]productRecordDetailList is empty,end");
            return;
        }
        List<BaseTenterCraft> baseTenterCraftDTOS = baseTenterCraftService.listByIds(baseTenterCraftIdList);
        if (CollectionUtils.isEmpty(baseTenterCraftDTOS)) {
            // 删除可优化工艺中采用此工艺的生产记录
            optimizeCraftService.removeByIds(baseTenterCraftIdList);
            log.info("[OptimizablCraftTask]baseTenterCraftDTOS is empty,removeByIds is {},end",baseTenterCraftIdList);
            return;
        }
        Set<Long> BaseTenterCraftIdSet = baseTenterCraftDTOS.stream().map(BaseTenterCraft::getId).collect(Collectors.toSet());
        Sets.SetView<Long> difference = Sets.difference(Sets.newHashSet(baseTenterCraftIdList), BaseTenterCraftIdSet);
        if (CollectionUtils.isNotEmpty(difference)) {
            // 删除可优化工艺中采用此工艺的生产记录
            optimizeCraftService.removeByIds(difference);
            log.info("[OptimizablCraftTask]removeByIds is {}",difference);
        }
        Map<String, List<BaseTenterCraft>> baseTenterCraftMap = baseTenterCraftDTOS.stream().collect(Collectors.groupingBy(BaseTenterCraft::getOrgCode));
        for (Map.Entry<String, List<BaseTenterCraft>> entry : baseTenterCraftMap.entrySet()) {
            String orgCode = entry.getKey();
            List<BaseTenterCraft> baseTenterCraftDTOList = entry.getValue();
            List<Long> tenterCraftIdList = baseTenterCraftDTOList.stream().map(BaseTenterCraft::getId).collect(Collectors.toList());

            List<BaseShapingParamConfig> baseShapingParamConfigDTOList = baseShapingParamConfigService.queryListByType(13);
            if (CollectionUtils.isEmpty(baseShapingParamConfigDTOList)) {
                // 删除可优化工艺中采用此工艺的生产记录
                optimizeCraftService.removeByIds(tenterCraftIdList);
                log.info("[OptimizablCraftTask]removeByIds is {}",tenterCraftIdList);
                continue;
            }
            Set<String> baseShapingParamConfigSet = baseShapingParamConfigDTOList.stream().map(BaseShapingParamConfig::getName).collect(Collectors.toSet());
            List<OptimizeCraftEnum> optimizeCraftEnumList = OptimizeCraftEnum.getOptimizeCraftEnum(baseShapingParamConfigSet);
            if (CollectionUtils.isEmpty(optimizeCraftEnumList)) {
                // 删除可优化工艺中采用此工艺的生产记录
                optimizeCraftService.removeByIds(tenterCraftIdList);
                log.info("[OptimizablCraftTask]removeByIds is {}",tenterCraftIdList);
                continue;
            }
            Map<String, Boolean> aloneConfig = queryAloneConfig(orgCode);
            List<OptimizeCraft> optimizeCraftList = new ArrayList<>();
            for (BaseTenterCraft baseTenterCraftDTO : baseTenterCraftDTOList) {
                Long tenterCraftDTOId = baseTenterCraftDTO.getId();
                OptimizeCraft optimizeCraft = new OptimizeCraft();
                Map<String, Object> suggestionMap = new HashMap<>();
                Map<String, List<Long>> contrastProductRecordIdMap = new HashMap<>();
                // 最近10条采用此工艺的生产记录实际生产计算的工艺
                List<Long> productInfoIdList = productRecordDetailService.queryProductInfoIdByBaseTenterCraftId(tenterCraftDTOId, endTime.minusMonths(3), endTime);
                if (CollectionUtils.isNotEmpty(productInfoIdList)) {
                    List<OptimizeCraftPageDTO> optimizeCraftPageDTOList = productRecordDetailService.queryOptimizeCraftData(productInfoIdList);
                    if (CollectionUtils.isNotEmpty(optimizeCraftPageDTOList) && optimizeCraftPageDTOList.size() > 4) {
                        // 用“工艺库工艺”与“最近10条采用此工艺的生产记录实际生产计算的工艺(不含无法计算出工艺的生产记录)”进行对比
                        // 出现连续“高于”或“低于”(均包含等于)工艺参数值5次及以上的数据，则触发工艺库对应工艺参数值的优化建议，建议内容为“生产记录实际计算的工艺参数中出现次数最多的值”；如无建议，则“优化建议”展示为“-”；
                        // 使用 baseTenterCraftDTO 中的工艺信息 和 historyProductInfoCarftDTOList 中的工艺信息 进行对比
                        compareCraftData(suggestionMap,baseTenterCraftDTO, optimizeCraftPageDTOList, optimizeCraftEnumList, aloneConfig);
                        contrastProductRecordIdMap.put("byId",optimizeCraftPageDTOList.stream().map(OptimizeCraftPageDTO::getProductRecordId).collect(Collectors.toList()));
                    }
                }
                log.info("[OptimizablCraftTask]baseTenterCraftDTO id is {},suggestionMap is {}", tenterCraftDTOId,JSON.toJSONString(suggestionMap));
                if (MapUtils.isEmpty(suggestionMap)) {
                    continue;
                }
                BeanUtils.copyProperties(baseTenterCraftDTO, optimizeCraft);
                optimizeCraft.setSuggestionJson(suggestionMap);
                optimizeCraft.setContrastProductRecordId(contrastProductRecordIdMap);
                optimizeCraft.setCraftUpdateTime(baseTenterCraftDTO.getUpdateTime());
                optimizeCraft.setCreateTime(LocalDateTime.now());
                optimizeCraftList.add(optimizeCraft);
            }
            // 删除可优化工艺中采用此工艺的生产记录
            optimizeCraftService.removeByIds(tenterCraftIdList);
            if (CollectionUtils.isNotEmpty(optimizeCraftList)) {
                optimizeCraftService.saveBatch(optimizeCraftList,optimizeCraftList.size());
            }
        }
        log.info("[OptimizablCraftTask]task end");
    }
    private void compareCraftData(Map<String, Object> suggestionMap,BaseTenterCraft baseTenterCraftDTO,List<OptimizeCraftPageDTO> optimizeCraftPageDTOList,List<OptimizeCraftEnum> optimizeCraftEnumList,Map<String, Boolean> aloneConfig) {
        try {
            Class<BaseTenterCraft> baseTenterCraftDTOClass = BaseTenterCraft.class;
            Class<OptimizeCraftPageDTO> optimizeCraftPageDTOClass = OptimizeCraftPageDTO.class;
            Map<String, Object> dynamicMap = baseTenterCraftDTO.parseDynamicField();
            Set<String> alreadyExitKey = suggestionMap.keySet();
            // 动态字段
            HashSet<String> dynamicFieldNameSet = Sets.newHashSet(OptimizeCraftEnum.WASHING_REAR_DOOR_WIDTH.getCraftParamName(), OptimizeCraftEnum.WEIGHT_AFTER_WASHING.getCraftParamName(),
                    OptimizeCraftEnum.LON.getCraftParamName(), OptimizeCraftEnum.LAT.getCraftParamName(), OptimizeCraftEnum.CRAFT_SHRINKAGE.getCraftParamName(),
                    OptimizeCraftEnum.UPPER_WARP_DENSITY.getCraftParamName(), OptimizeCraftEnum.LOWER_WARP_DENSITY.getCraftParamName());
            // 温度 循环风 门幅单独处理
            HashSet<String> individualizationFieldNameSet = Sets.newHashSet(OptimizeCraftEnum.DRYING_ROOM_TEMP.getCraftParamName(), OptimizeCraftEnum.FAN_SPEED.getCraftParamName(),
                    OptimizeCraftEnum.CIRCULATING_AIR_UPPER.getCraftParamName(),OptimizeCraftEnum.CIRCULATING_AIR_LOWER.getCraftParamName());
            for (OptimizeCraftEnum optimizeCraftEnum : optimizeCraftEnumList) {
                String fieldName = optimizeCraftEnum.getCraftParamName();
                if (alreadyExitKey.contains(fieldName)) {
                    continue;
                }
                // 温度 循环风 门幅单独处理
                if (individualizationFieldNameSet.contains(fieldName)) {
                    continue;
                }
                try {
                    Field optimizeCraftField = optimizeCraftPageDTOClass.getDeclaredField(optimizeCraftEnum.getCraftParamName());
                    optimizeCraftField.setAccessible(true);

                    Object tenterCraftValue;
                    // 上机门幅 带-字符串  Double upperDoorWidth
                    // 落机门幅 带-字符串  Double lowerDoorWidth
                    if (OptimizeCraftEnum.UPPER_DOOR_WIDTH.getCraftParamName().equals(fieldName) || OptimizeCraftEnum.LANDING_DOOR_WIDTH.getBaseShapingParamName().equals(fieldName)) {
                        if (MapUtils.isEmpty(dynamicMap)) {
                            continue;
                        }
                        tenterCraftValue = dynamicMap.get(fieldName);
                        if (Objects.isNull(tenterCraftValue) || StringUtils.isBlank(tenterCraftValue.toString())) {
                            continue;
                        }
                        String[] split = tenterCraftValue.toString().split("-");
                        tenterCraftValue = split[0];
                    } else if (dynamicFieldNameSet.contains(fieldName)) {
                        // 还原门幅、洗后门幅  字符串  字符串
                        // 定前克重 字符串  字符串 preWeight
                        // 定后克重 字符串  Integer gramHeft
                        // 还原克重、洗后克重 字符串  字符串
                        // 经度，维度 字符串 BigDecimal
                        // 上机纬密 字符串  字符串 upperWeftDensity
                        tenterCraftValue = dynamicMap.get(fieldName);
                    } else {
                        Field tenterCraftField = baseTenterCraftDTOClass.getDeclaredField(fieldName);
                        tenterCraftField.setAccessible(true);
                        tenterCraftValue = tenterCraftField.get(baseTenterCraftDTO);
                    }
                    if (Objects.isNull(tenterCraftValue)) {
                        continue;
                    }
                    if (tenterCraftValue instanceof String && StringUtils.isBlank(String.valueOf(tenterCraftValue))) {
                        continue;
                    }
                    // 非数字类型
                    if (!Validator.isNumber(String.valueOf(tenterCraftValue))) {
                        continue;
                    }
                    List<Object> optimizeCraftValueList = new ArrayList<>();
                    for (OptimizeCraftPageDTO optimizeCraftPageDTO : optimizeCraftPageDTOList) {
                        Object optimizeCraftValue = optimizeCraftField.get(optimizeCraftPageDTO);
                        optimizeCraftValueList.add(optimizeCraftValue);
                    }
                    List<BigDecimal> actualValueList = optimizeCraftValueList.stream().map(v -> {
                        if (Objects.isNull(v) || !Validator.isNumber(String.valueOf(v))) {
                            return null;
                        }
                        return new BigDecimal(String.valueOf(v));
                    }).collect(Collectors.toList());
                    List<BigDecimal> sectionList = BigDecimalUtils.findFirstContinuousSection(actualValueList, tenterCraftValue);
                    if (CollectionUtils.isNotEmpty(sectionList)) {
                        /*BigDecimal sameValueFromList = BigDecimalUtils.filterMaxSameValueFromList(sectionList);
                        if (Objects.nonNull(sameValueFromList) && sameValueFromList.compareTo(new BigDecimal(String.valueOf(tenterCraftValue))) != 0) {
                            suggestionMap.put(fieldName, sameValueFromList);
                        }*/
                        putToObjMapIfSameValueNotEqCraftData(new BigDecimal(String.valueOf(tenterCraftValue)),suggestionMap,fieldName, sectionList);
                    }

                } catch (NoSuchFieldException | IllegalAccessException e) {
                    log.info("[OptimizablCraftTask][compareCraftData]fieldName is {},error is ",fieldName,e);
                }
            }
            Set<String> optimizeCraftFieldSet = optimizeCraftEnumList.stream().map(OptimizeCraftEnum::getCraftParamName).collect(Collectors.toSet());
            // 温度 循环风 门幅JSON 单独处理
            if (optimizeCraftFieldSet.contains(OptimizeCraftEnum.DRYING_ROOM_TEMP.getCraftParamName())) {
                compareCraftDataForDryingRoomTempJson(baseTenterCraftDTO, optimizeCraftPageDTOList, suggestionMap, aloneConfig);
            }
            // 门幅JSON
            if (optimizeCraftFieldSet.contains(OptimizeCraftEnum.TOTAL_AMPLITUDE.getCraftParamName())) {
                compareCraftDataForDoorWidthActualJson(baseTenterCraftDTO, optimizeCraftPageDTOList, suggestionMap, aloneConfig);
            }

            // 循环风
            if (optimizeCraftFieldSet.contains(OptimizeCraftEnum.FAN_SPEED.getCraftParamName())) {
                compareCraftDataForFanSpeedJson(baseTenterCraftDTO, optimizeCraftPageDTOList, suggestionMap, aloneConfig);
            }
            // 循环风 上下
            if (optimizeCraftFieldSet.contains(OptimizeCraftEnum.CIRCULATING_AIR_UPPER.getCraftParamName())) {
                compareCraftDataForCirculatingAirUpperOrLowerJson(baseTenterCraftDTO, optimizeCraftPageDTOList, suggestionMap, aloneConfig,dynamicMap,true);
            }
            if (optimizeCraftFieldSet.contains(OptimizeCraftEnum.CIRCULATING_AIR_LOWER.getCraftParamName())) {
                compareCraftDataForCirculatingAirUpperOrLowerJson(baseTenterCraftDTO, optimizeCraftPageDTOList, suggestionMap, aloneConfig,dynamicMap,false);
            }
        } catch (Exception e) {
            log.error("[OptimizablCraftTask][compareCraftData]baseTenterCraftDTO is is {},error is ",baseTenterCraftDTO.getId(),e);
        }

    }

    /**
     * 温度
     */
    private void compareCraftDataForDryingRoomTempJson(BaseTenterCraft baseTenterCraftDTO, List<OptimizeCraftPageDTO> optimizeCraftPageDTOList, Map<String,Object> suggestionMap, Map<String, Boolean> aloneConfig) {
        // 总值
        Set<String> alreadyExitKey = suggestionMap.keySet();
        if (!alreadyExitKey.contains(OptimizeCraftEnum.DRYING_ROOM_TEMP.getCraftParamName())) {
            BigDecimal dryingRoomTemp = baseTenterCraftDTO.getDryingRoomTemp();
            List<BigDecimal> totalValueList = new ArrayList<>();
            for (OptimizeCraftPageDTO optimizeCraftPageDTO : optimizeCraftPageDTOList) {
                Object dryingRoomPresetTemp = optimizeCraftPageDTO.getDryingRoomPresetTemp();
                LinkedHashMap<String, Integer> dryingRoomPresetTempMap = BigDecimalUtils.buildBaseTenterJson(null, dryingRoomPresetTemp, StenterInfluxDBEnum.DRYING_ROOM_ACTUAL_TEMP.getActKey());
                totalValueList.add(filterMaxSameValueFromMap(dryingRoomPresetTempMap));
            }
            List<BigDecimal> sectionList = BigDecimalUtils.findFirstContinuousSection(totalValueList, dryingRoomTemp);
            if (CollectionUtils.isNotEmpty(sectionList)) {
                putToObjMapIfSameValueNotEqCraftData(dryingRoomTemp,suggestionMap,OptimizeCraftEnum.DRYING_ROOM_TEMP.getCraftParamName(), sectionList);
            }
        }


        if (aloneConfig.get(OptimizeCraftEnum.DRYING_ROOM_TEMP.getCraftParamName())) {
            // 每节单独计算
            String settingKey = StenterInfluxDBEnum.DRYING_ROOM_ACTUAL_TEMP.getSettingKey();
            String actKey = StenterInfluxDBEnum.DRYING_ROOM_ACTUAL_TEMP.getActKey();
            Object craftJsonValue = baseTenterCraftDTO.getDryingRoomPresetTemp();
            if (Objects.isNull(craftJsonValue)) {
                return;
            }
            List<LinkedHashMap<String, Integer>> dryingRoomTempList = new ArrayList<>();
            for (OptimizeCraftPageDTO optimizeCraftPageDTO : optimizeCraftPageDTOList) {
                Object dryingRoomPresetTemp = optimizeCraftPageDTO.getDryingRoomPresetTemp();
                LinkedHashMap<String, Integer> dryingRoomPresetTempMap = BigDecimalUtils.buildBaseTenterJson(null, dryingRoomPresetTemp, actKey);
                dryingRoomTempList.add(dryingRoomPresetTempMap);
            }
            Map<String, BigDecimal> craftJsonMap = JSON.parseObject(JSON.toJSONString(craftJsonValue), new TypeReference<LinkedHashMap<String, BigDecimal>>() {});
            Map<String,BigDecimal> sectionMap = new LinkedHashMap<>();
            for (int i = 1; i <= 10; i++) {
                if (alreadyExitKey.contains(settingKey + i)) {
                    continue;
                }
                List<BigDecimal> eachValueList = new ArrayList<>();
                for (LinkedHashMap<String, Integer> linkedHashMap : dryingRoomTempList) {
                    Integer value = linkedHashMap.get(actKey + i);
                    if (Objects.nonNull(value)) {
                        eachValueList.add(BigDecimal.valueOf(value));
                    } else {
                        eachValueList.add(null);
                    }
                }
                List<BigDecimal> section = BigDecimalUtils.findFirstContinuousSection(eachValueList, craftJsonMap.get(settingKey + i));
                if (CollectionUtils.isNotEmpty(section)) {
                    putToBigDecimalMapIfSameValueNotEqCraftData(craftJsonMap.get(settingKey + i),sectionMap,settingKey + i, section);
                }
            }
            if (MapUtils.isNotEmpty(sectionMap)) {
                suggestionMap.put(settingKey,sectionMap);
            }

        }
    }

    /**
     * 门幅
     */
    private void compareCraftDataForDoorWidthActualJson(BaseTenterCraft baseTenterCraftDTO, List<OptimizeCraftPageDTO> optimizeCraftPageDTOList, Map<String,Object> suggestionMap, Map<String, Boolean> aloneConfig) {
        Set<String> alreadyExitKey = suggestionMap.keySet();
        if (aloneConfig.get(OptimizeCraftEnum.TOTAL_AMPLITUDE.getCraftParamName())) {
            // 每节单独计算
            String key = StenterInfluxDBEnum.DOOR_WIDTH_ACTUAL.getActKey();
            Object craftJsonValue = baseTenterCraftDTO.getDoorWidthActual();
            if (Objects.isNull(craftJsonValue)) {
                return;
            }
            List<LinkedHashMap<String, Object>> doorWidthActualList = new ArrayList<>();
            for (OptimizeCraftPageDTO optimizeCraftPageDTO : optimizeCraftPageDTOList) {
                Object doorWidthActual = optimizeCraftPageDTO.getDoorWidthActual();
                LinkedHashMap<String, Object> doorWidthActualMap = BigDecimalUtils.buildBaseTenterDoorWidthActualJson(null, doorWidthActual, key);
                doorWidthActualList.add(doorWidthActualMap);
            }
            Map<String, BigDecimal> craftJsonMap = JSON.parseObject(JSON.toJSONString(craftJsonValue), new TypeReference<LinkedHashMap<String, BigDecimal>>() {});
            Map<String,BigDecimal> sectionMap = new LinkedHashMap<>();

            for (int i = 1; i <= 10; i++) {
                if (alreadyExitKey.contains(key + i)) {
                    continue;
                }
                List<BigDecimal> eachValueList = new ArrayList<>();
                for (LinkedHashMap<String, Object> linkedHashMap : doorWidthActualList) {
                    Object value = linkedHashMap.get(key + i);
                    if (Objects.nonNull(value) && Validator.isNumber(String.valueOf(value))) {
                        eachValueList.add(new BigDecimal(String.valueOf(value)));
                    } else {
                        eachValueList.add(null);
                    }
                }
                List<BigDecimal> section = BigDecimalUtils.findFirstContinuousSection(eachValueList, craftJsonMap.get(key + i));
                if (CollectionUtils.isNotEmpty(section)) {
                    putToBigDecimalMapIfSameValueNotEqCraftData(craftJsonMap.get(key + i),sectionMap,key + i, section);
                }
            }
            if (MapUtils.isNotEmpty(sectionMap)) {
                suggestionMap.put(key,sectionMap);
            }
        }
    }

    /**
     * 循环风
     */
    private void compareCraftDataForFanSpeedJson(BaseTenterCraft baseTenterCraftDTO, List<OptimizeCraftPageDTO> optimizeCraftPageDTOList, Map<String,Object> suggestionMap, Map<String, Boolean> aloneConfig) {
        // 总值
        Set<String> alreadyExitKey = suggestionMap.keySet();
        if (!alreadyExitKey.contains(OptimizeCraftEnum.FAN_SPEED.getCraftParamName())) {
            BigDecimal fanSpeed = baseTenterCraftDTO.getFanSpeed();
            List<BigDecimal> totalValueList = new ArrayList<>();
            for (OptimizeCraftPageDTO optimizeCraftPageDTO : optimizeCraftPageDTOList) {
                Object speciCycleWindSpeed = optimizeCraftPageDTO.getSpeciCycleWindSpeed();
                LinkedHashMap<String, Integer> speciCycleWindSpeedMap = BigDecimalUtils.buildBaseTenterJson(null, speciCycleWindSpeed, StenterInfluxDBEnum.CYCLE_WIND_SPEED.getActKey());
                totalValueList.add(filterMaxSameValueFromMap(speciCycleWindSpeedMap));
            }
            List<BigDecimal> sectionList = BigDecimalUtils.findFirstContinuousSection(totalValueList, fanSpeed);
            if (CollectionUtils.isNotEmpty(sectionList)) {
                putToObjMapIfSameValueNotEqCraftData(fanSpeed,suggestionMap,OptimizeCraftEnum.FAN_SPEED.getCraftParamName(),sectionList);
            }
        }


        if (aloneConfig.get(OptimizeCraftEnum.FAN_SPEED.getCraftParamName())) {
            // 每节单独计算
            String settingKey = StenterInfluxDBEnum.CYCLE_WIND_SPEED.getSettingKey();
            String actKey = StenterInfluxDBEnum.CYCLE_WIND_SPEED.getActKey();
            Object craftJsonValue = baseTenterCraftDTO.getSpeciCycleWindSpeed();
            if (Objects.isNull(craftJsonValue)) {
                return;
            }
            List<LinkedHashMap<String, Integer>> dryingRoomPresetList = new ArrayList<>();
            for (OptimizeCraftPageDTO optimizeCraftPageDTO : optimizeCraftPageDTOList) {
                Object speciCycleWindSpeed = optimizeCraftPageDTO.getSpeciCycleWindSpeed();
                LinkedHashMap<String, Integer> dryingRoomPresetTempMap = BigDecimalUtils.buildBaseTenterJson(null, speciCycleWindSpeed, actKey);
                dryingRoomPresetList.add(dryingRoomPresetTempMap);
            }
            Map<String, BigDecimal> craftJsonMap = JSON.parseObject(JSON.toJSONString(craftJsonValue), new TypeReference<LinkedHashMap<String, BigDecimal>>() {});
            Map<String,BigDecimal> sectionMap = new LinkedHashMap<>();

            for (int i = 1; i <= 10; i++) {
                if (alreadyExitKey.contains(settingKey + i)) {
                    continue;
                }
                List<BigDecimal> eachValueList = new ArrayList<>();
                for (LinkedHashMap<String, Integer> linkedHashMap : dryingRoomPresetList) {
                    Integer value = linkedHashMap.get(actKey + i);
                    if (Objects.nonNull(value)) {
                        eachValueList.add(BigDecimal.valueOf(value));
                    } else {
                        eachValueList.add(null);
                    }
                }
                List<BigDecimal> section = BigDecimalUtils.findFirstContinuousSection(eachValueList, craftJsonMap.get(settingKey + i));
                if (CollectionUtils.isNotEmpty(section)) {
                    putToBigDecimalMapIfSameValueNotEqCraftData(craftJsonMap.get(settingKey + i),sectionMap,settingKey + i,section);
                }
            }
            if (MapUtils.isNotEmpty(sectionMap)) {
                suggestionMap.put(settingKey,sectionMap);
            }
        }
    }

    /**
     * 循环风上下
     */
    private void compareCraftDataForCirculatingAirUpperOrLowerJson(BaseTenterCraft baseTenterCraftDTO, List<OptimizeCraftPageDTO> optimizeCraftPageDTOList, Map<String,Object> suggestionMap, Map<String, Boolean> aloneConfig,Map<String, Object> dynamicMap,boolean airUpper) {
        if (Objects.isNull(dynamicMap)) {
            return;
        }
        Object baseTenterCraftTotalValue;
        Object baseTenterCraftEachValue;
        String key;
        String jsonMapKey;
        if (airUpper) {
            key = OptimizeCraftEnum.CIRCULATING_AIR_UPPER.getCraftParamName();
            jsonMapKey = "circulatingAirUpperMap";
            baseTenterCraftTotalValue = dynamicMap.get(key);
            baseTenterCraftEachValue = dynamicMap.get("circulatingAirUpperMap");
        } else {
            key = OptimizeCraftEnum.CIRCULATING_AIR_LOWER.getCraftParamName();
            jsonMapKey = "circulatingAirLowerMap";
            baseTenterCraftTotalValue = dynamicMap.get(key);
            baseTenterCraftEachValue = dynamicMap.get("circulatingAirLowerMap");
        }
        if (Objects.isNull(baseTenterCraftTotalValue)) {
            return;
        }

        Set<String> alreadyExitKey = suggestionMap.keySet();
        List<LinkedHashMap<String, Integer>> speciCycleWindSpeedList = new ArrayList<>();
        for (OptimizeCraftPageDTO optimizeCraftPageDTO : optimizeCraftPageDTOList) {
            Object speciCycleWindSpeed = optimizeCraftPageDTO.getSpeciCycleWindSpeed();
            LinkedHashMap<String, Integer> cycleWindSpeedMap = BigDecimalUtils.buildBaseTenterJson(null, speciCycleWindSpeed, StenterInfluxDBEnum.CYCLE_WIND_SPEED.getActKey());
            LinkedHashMap<String, Integer> speciCycleWindSpeedMap = BigDecimalUtils.transferMapKey(cycleWindSpeedMap, StenterInfluxDBEnum.CYCLE_WIND_SPEED.getActKey(), StenterInfluxDBEnum.CYCLE_WIND_SPEED.getSettingKey());
            LinkedHashMap<String, Integer> circulatingAirMap;
            if (airUpper) {
                circulatingAirMap = parseCirculatingAirUpperOrLower(speciCycleWindSpeedMap, 10, true, key);
            } else {
                circulatingAirMap = parseCirculatingAirUpperOrLower(speciCycleWindSpeedMap, 10, false, key);
            }
            log.info("[OptimizablCraftTask][compareCraftDataForCirculatingAirUpperOrLowerJson] baseTenterCraftDTO id is {},circulatingAirMap is {}", baseTenterCraftDTO.getId(),JSON.toJSONString(circulatingAirMap));

            speciCycleWindSpeedList.add(circulatingAirMap);
        }

        // 总值
        if (!alreadyExitKey.contains(key)) {

            List<BigDecimal> totalValueList = new ArrayList<>();
            for (LinkedHashMap<String, Integer> linkedHashMap : speciCycleWindSpeedList) {
                totalValueList.add(filterMaxSameValueFromMap(linkedHashMap));
            }
            List<BigDecimal> sectionList = BigDecimalUtils.findFirstContinuousSection(totalValueList, baseTenterCraftTotalValue);
            if (CollectionUtils.isNotEmpty(sectionList)) {
                putToObjMapIfSameValueNotEqCraftData(new BigDecimal(String.valueOf(baseTenterCraftTotalValue)),suggestionMap,key,sectionList);
            }
        }


        if (aloneConfig.get(OptimizeCraftEnum.FAN_SPEED.getCraftParamName()) && Objects.nonNull(baseTenterCraftEachValue)) {
            // 每节单独计算
            Map<String, BigDecimal> craftJsonMap = JSON.parseObject(JSON.toJSONString(baseTenterCraftEachValue), new TypeReference<LinkedHashMap<String, BigDecimal>>() {});
            Map<String,BigDecimal> sectionMap = new LinkedHashMap<>();

            for (int i = 1; i <= 10; i++) {
                if (alreadyExitKey.contains(key + i)) {
                    continue;
                }
                List<BigDecimal> eachValueList = new ArrayList<>();
                for (LinkedHashMap<String, Integer> linkedHashMap : speciCycleWindSpeedList) {
                    Integer value = linkedHashMap.get(key + i);
                    if (Objects.nonNull(value)) {
                        eachValueList.add(BigDecimal.valueOf(value));
                    } else {
                        eachValueList.add(null);
                    }
                }
                List<BigDecimal> section = BigDecimalUtils.findFirstContinuousSection(eachValueList, craftJsonMap.get(key + i));
                if (CollectionUtils.isNotEmpty(section)) {
                    putToBigDecimalMapIfSameValueNotEqCraftData(craftJsonMap.get(key + i),sectionMap,key + i, section);
                }
            }
            if (MapUtils.isNotEmpty(sectionMap)) {
                suggestionMap.put(jsonMapKey,sectionMap);
            }
        }
    }

    private Map<String,Boolean> queryAloneConfig(String orgCode) {
        return Map.of(
                OptimizeCraftEnum.DRYING_ROOM_TEMP.getCraftParamName(),true,
                OptimizeCraftEnum.FAN_SPEED.getCraftParamName(),true,
                OptimizeCraftEnum.TOTAL_AMPLITUDE.getCraftParamName(),true
        );
    }


    public LinkedHashMap<String, Integer> parseCirculatingAirUpperOrLower(Object cycleWindSpeed, Integer dryingRoomCount, boolean upper, String key) {
        if (Objects.isNull(cycleWindSpeed)) {
            return null;
        }
        LinkedHashMap<String, Integer> resultMap = new LinkedHashMap<>();
        LinkedHashMap<String, Object> actualMap = JSON.parseObject(JSON.toJSONString(cycleWindSpeed), LinkedHashMap.class);
        for (int i = 1; i <= dryingRoomCount; i++) {
            int index = upper ? i + i % 2 - 1 : i + i % 2;
            Object value = actualMap.get("speciCycleWindSpeed" + index);
            if (Objects.isNull(value) || !Validator.isNumber(String.valueOf(value))) {
                resultMap.put(key + i, null);
                continue;
            }
            BigDecimal bigDecimal = new BigDecimal(String.valueOf(value));
            resultMap.put(key + i, bigDecimal.intValue());
        }
        return resultMap;
    }

    public BigDecimal filterMaxSameValueFromMap(LinkedHashMap<String, Integer> map) {
        if (MapUtils.isEmpty(map)) {
            return null;
        }
        List<BigDecimal> BigDecimalList = map.values().stream().filter(Objects::nonNull).map(BigDecimal::new).collect(Collectors.toList());
        return BigDecimalUtils.filterMaxSameValueFromList(BigDecimalList);
    }

    private void putToObjMapIfSameValueNotEqCraftData(BigDecimal craftData,Map<String,Object> suggestionMap,String key,List<BigDecimal> section) {
        BigDecimal sameValueFromList = BigDecimalUtils.filterMaxSameValueFromList(section);
        if (Objects.nonNull(sameValueFromList) && sameValueFromList.compareTo(craftData) != 0) {
            suggestionMap.put(key,sameValueFromList);
        }
    }

    private void putToBigDecimalMapIfSameValueNotEqCraftData(BigDecimal craftData,Map<String,BigDecimal> sectionMap,String key,List<BigDecimal> section) {
        BigDecimal sameValueFromList = BigDecimalUtils.filterMaxSameValueFromList(section);
        if (Objects.nonNull(sameValueFromList) && sameValueFromList.compareTo(craftData) != 0) {
            sectionMap.put(key,sameValueFromList);
        }
    }
}
